package com.one.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.one.config.WechatAuthConfig;
import com.one.constant.RedisPrefixConstant;
import com.one.constant.RequestReturnConstant;
import com.one.service.WechatAuthService;
import com.one.util.HttpClient4Util;
import com.one.util.RedisUtils;
import com.one.util.RequestReturn;
import com.one.util.RequestReturnFactory;
import com.one.vo.UserVo;
import com.one.vo.WechatUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Author ShiWen
 * @date 2021/12/30 9:32
 * @Version 1.0
 * @Description 微信网页授权操作入口
 */
@RestController
@Slf4j
public class WechatAuthController {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private WechatAuthService wechatAuthService;
    @Autowired
    private WechatAuthConfig wechatAuthConfig;
    /**
     * @author ShiWen
     * @date 2021/12/30 9:32
     * @param 
     * @return 
     * @description 获取请求微信公众测试平台，手动授权，获取code的连接（完整url）
     */
    @GetMapping("/codeUrl")
    public RequestReturn<Map<String,Object>> wechatAuthCodeUrl(){
        Map<String,Object> map = new HashMap<>();
        // 官方提供的标准url示例：https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
        StringBuffer codeUrl = new StringBuffer(wechatAuthConfig.getCodeUri());
        codeUrl.append("?appid=").append(wechatAuthConfig.getAppId())
                .append("&redirect_uri=").append(wechatAuthConfig.getRedirectUri())
                .append("&response_type=code")
                .append("&scope=snsapi_userinfo")
                .append("&state=").append(UUID.randomUUID().toString().substring(0,6))
                .append("#wechat_redirect");
        log.info("———— 1 请求微信官方，通过用户手动授权，获取code,完整地址：{} ————",codeUrl);
        map.put("wechatUtl",codeUrl);
        return RequestReturnFactory.success(map);
    }
    /**
     * @author ShiWen
     * @date 2021/12/30 10:11
     * @param
     * @return
     * @description 接收微信官方异步回调code
     */
    @RequestMapping("/backUrl")
    public RequestReturn<Map<String,Object>> backCode(HttpServletRequest request){
        // 用户手动授权后，页面跳转至 redirect_uri/?code=CODE&state=STATE。
        // code说明 ： code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
        //获取回调的code值
        String backCode = request.getParameter("code");
        log.info("———— 2 微信官方授权回调code：{} ——————",backCode);
        //获取回调的state值
        String backState = request.getParameter("state");
        log.info("———— 2 微信官方授权回调backState：{} ——————",backState);
        // 统一返回
        Map<String,Object> map = new HashMap<>();
        map.put("code",backCode);
        map.put("state",backState);
        // TODO 验证code的有效性
        // 获取code后，请求以下链接获取access_token：
        // https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        StringBuilder accessTokenUrl = new StringBuilder(wechatAuthConfig.getAccessTokenUri());
        accessTokenUrl.append("?appid=").append(wechatAuthConfig.getAppId())
                .append("&secret=").append(wechatAuthConfig.getAppSecret())
                .append("&code=").append(backCode)
                .append("&grant_type=authorization_code");
        log.info("———— 3 微信官方异步回调code值，重新请求微信官方，获取access_token,完整url:{}————",accessTokenUrl);

        // 程序中发送HTTP请求微信官方，获取access_token
        String backJson = HttpClient4Util.getResponse4GetAsString(accessTokenUrl.toString(),"utf-8");
        log.info("———— 3 通过code，请求微信官方，获取access_token，同步返回的json结果:{}————",backJson);

        // json内容解析，获取access_token （拉取用户信息的凭证）和 openid
        // 官方返回成功：{"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE"}
        // 返回失败 ：{"errcode":40029,"errmsg":"invalid code"}
        JSONObject jsonObject = JSON.parseObject(backJson);
        // 判断是否请求错误
        if (!StringUtils.isEmpty(jsonObject.getString("errcode"))){
            log.error("———— 3 通过code，请求微信官方，返回错误结果:{}————",backJson);
            map.put("errinfo",backJson);
            return RequestReturnFactory.fail(map);
        }

//        map.put("accessinfo",backJson);
        // 请求微信官方，获取用户信息
        // 如果网页授权作用域为snsapi_userinfo，则此时开发者可以通过access_token和openid拉取用户信息了。
        //请求方法http：GET（请使用https协议） https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

        // 获取拉取用户信息的access_token和openid
        String accessToken = jsonObject.getString("access_token");
        String openId = jsonObject.getString("openid");
        /**
         *  判断微信是否被绑定账号
         */
        UserVo userVo = wechatAuthService.findWechatByOpenId(openId);
        if (userVo!=null){
            // 代表登录成功
            //生成token
            String token = UUID.randomUUID().toString().replace("-","").substring(0,24);
            // 登录令牌存入redis
            redisUtils.set(RedisPrefixConstant.LOGIN_TOKEN+token,userVo);
            map.put("token",token);
            return RequestReturnFactory.success(map);
        }
        StringBuilder userInfoUrl = new StringBuilder(wechatAuthConfig.getUserInfoUri());
        log.info("———— 4 请求微信官方，获取用户信息，完整请求地址：{} ————", userInfoUrl);
        userInfoUrl.append("?access_token=").append(accessToken)
                .append("&openid=").append(openId)
                .append("&lang=zh_CN");

        // 请求微信官方，获取用户信息
        String userInfoJson = HttpClient4Util.getResponse4GetAsString(userInfoUrl.toString(),"utf-8");
        log.info("———— 4 请求微信官方，返回完整的用户信息：{} ————", userInfoJson);
        // 封装返回结果
        map.put("accessToken",accessToken);
        map.put("openId",openId);
        JSONObject jsonObject1 = JSON.parseObject(userInfoJson);
//        WechatUser wechatUser = WechatUser.builder().openid(openId).nickname(jsonObject1.getString("nickname"))
//                        .headimgurl(jsonObject1.getString("headimgurl")).sex(jsonObject1.getInteger("sex")).build();
        map.put("userInfoJson",jsonObject1);
        //检验授权凭证（access_token）是否有效
        //请求方法
        //http：GET（请使用https协议） https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID
        StringBuilder authUrl = new StringBuilder(wechatAuthConfig.getAuthUri());
        authUrl.append("?access_token=").append(accessToken)
                .append("&openid=").append(openId);
        String authJson = HttpClient4Util.getResponse4GetAsString(authUrl.toString(),"utf-8");
        log.info("———— 5 检验授权凭证（access_token）是否有效,返回结果信息：{} ————", authJson);
        return RequestReturnFactory.success(RequestReturnConstant.RETURN_WECHAT_AUTH_REGIS_CODE,RequestReturnConstant.RETURN_WECHAT_AUTH_REGIS_MESSAGE,map);
    }


}
